"""
数据库工具 - 事务管理和常用操作
"""
from contextlib import contextmanager
from functools import wraps
from typing import Callable, Any
from sqlalchemy.orm import Session
from sqlalchemy.exc import SQLAlchemyError
import logging

from app.models.database import SessionLocal

logger = logging.getLogger(__name__)


@contextmanager
def get_db_transaction():
    """
    数据库事务上下文管理器
    
    使用示例:
        with get_db_transaction() as db:
            user = User(username="test")
            db.add(user)
            # 自动 commit，出错自动 rollback
    
    Yields:
        Session: 数据库会话
    """
    db: Session = SessionLocal()
    try:
        yield db
        db.commit()
        logger.debug("数据库事务提交成功")
    except SQLAlchemyError as e:
        db.rollback()
        logger.error(f"数据库事务回滚: {str(e)}")
        raise
    except Exception as e:
        db.rollback()
        logger.error(f"数据库事务回滚 (非 SQL 错误): {str(e)}")
        raise
    finally:
        db.close()


def transactional(func: Callable) -> Callable:
    """
    事务装饰器（用于同步函数）
    
    使用示例:
        @transactional
        def create_user(username: str, db: Session):
            user = User(username=username)
            db.add(user)
            return user
    
    Args:
        func: 要装饰的函数（必须有 db 参数）
    
    Returns:
        装饰后的函数
    """
    @wraps(func)
    def wrapper(*args, **kwargs):
        # 检查是否已经传入了 db
        if 'db' in kwargs and kwargs['db'] is not None:
            # 已有 db，直接调用
            return func(*args, **kwargs)
        
        # 创建新的事务
        with get_db_transaction() as db:
            kwargs['db'] = db
            return func(*args, **kwargs)
    
    return wrapper


def safe_commit(db: Session, operation_name: str = "操作") -> bool:
    """
    安全地提交数据库事务
    
    Args:
        db: 数据库会话
        operation_name: 操作名称（用于日志）
    
    Returns:
        bool: 是否成功
    """
    try:
        db.commit()
        logger.debug(f"{operation_name}成功")
        return True
    except SQLAlchemyError as e:
        db.rollback()
        logger.error(f"{operation_name}失败: {str(e)}")
        return False


def safe_delete(db: Session, obj: Any, operation_name: str = "删除") -> bool:
    """
    安全地删除数据库对象
    
    Args:
        db: 数据库会话
        obj: 要删除的对象
        operation_name: 操作名称
    
    Returns:
        bool: 是否成功
    """
    try:
        db.delete(obj)
        db.commit()
        logger.info(f"{operation_name}成功: {type(obj).__name__}")
        return True
    except SQLAlchemyError as e:
        db.rollback()
        logger.error(f"{operation_name}失败: {str(e)}")
        return False


def safe_add(db: Session, obj: Any, operation_name: str = "添加") -> bool:
    """
    安全地添加数据库对象
    
    Args:
        db: 数据库会话
        obj: 要添加的对象
        operation_name: 操作名称
    
    Returns:
        bool: 是否成功
    """
    try:
        db.add(obj)
        db.commit()
        db.refresh(obj)  # 刷新对象以获取数据库生成的字段
        logger.info(f"{operation_name}成功: {type(obj).__name__}")
        return True
    except SQLAlchemyError as e:
        db.rollback()
        logger.error(f"{operation_name}失败: {str(e)}")
        return False


def batch_operation(db: Session, operations: list, operation_name: str = "批量操作") -> tuple[bool, int]:
    """
    批量操作（全部成功或全部失败）
    
    Args:
        db: 数据库会话
        operations: 操作列表（每个元素是一个 lambda 函数）
        operation_name: 操作名称
    
    Returns:
        tuple: (是否成功, 成功数量)
    
    使用示例:
        operations = [
            lambda: db.add(User(username="user1")),
            lambda: db.add(User(username="user2")),
        ]
        success, count = batch_operation(db, operations, "批量创建用户")
    """
    try:
        success_count = 0
        for op in operations:
            op()
            success_count += 1
        
        db.commit()
        logger.info(f"{operation_name}成功: {success_count} 条")
        return True, success_count
    
    except Exception as e:
        db.rollback()
        logger.error(f"{operation_name}失败: {str(e)}")
        return False, 0

